package scenic.toolkit;

import scenic.SceneContainer;

public class TextSetter {
	private SceneContainer scene;
	private double frameWidth;
	private ParagraphStyle style;
	
	public static class TextObject {
		public ElementView element;
		public double width;
		public double ascent;
		public double descent;
		boolean isSpace;
		int index;
	}
	
	private TextObject objects[] = new TextObject[0];
	private int numObjects;
	
	private ElementView element;
	private int index;

	private double top;
	private double maxAscent;
	private double maxDescent;
	private double totalWidth;

	public TextSetter(SceneContainer scene, ParagraphStyle style, double frameWidth) {
		this.scene = scene;
		this.style = style;
		this.frameWidth = frameWidth;
		resizeObjects(10);
	}

	private void resizeObjects(int size) {
		TextObject newObjects[] = new TextObject[size];
		
		System.arraycopy(objects, 0, newObjects, 0, objects.length);
		for(int i = objects.length; i < newObjects.length; i++)
			newObjects[i] = new TextObject();
		
		objects = newObjects;
	}
	
	public void beginElement(ElementView element) {
		this.element = element;
		index = 0;
	}
	
	public void addObject(double ascent, double descent, 
			double width, boolean isSpace) {
		if(totalWidth + width > frameWidth && numObjects > 0 && !isSpace) {
			drawLine(false);
		}
		if(numObjects >= objects.length)
			resizeObjects(objects.length * 2);

		TextObject object = objects[numObjects++];
		
		object.element = element;
		object.width = width;
		object.ascent = ascent;
		object.descent = descent;
		object.isSpace = isSpace;
		object.index = index++;
		maxAscent = Math.max(maxAscent, ascent);
		maxDescent = Math.max(maxDescent, descent);
		totalWidth += width;
	}
	
	public void flush() {
		drawLine(true);
	}
	
	public void endLine() {
		drawLine(true);
	}
	
	private void drawObjects(int lineEnd) {
		int i = 0;
		double x = 0;
		double y = top + maxAscent; 		
		
		while(i < lineEnd) {
			TextObject object = objects[i];
			int start = i;
			double startX = x;
			
			while(i < lineEnd && objects[i].element == object.element) {
				x += objects[i].width;
				i++;
			}
			
			object.element.drawObjects(scene, startX, y, objects, start, object.index, i - start);
		}
	}
	
	private void calcAscentAndDescent(int end) {
		maxAscent = 0;
		maxDescent = 0;
		for(int i = 0; i < end; i++) {
			maxAscent = Math.max(maxAscent, objects[i].ascent);
			maxDescent = Math.max(maxDescent, objects[i].descent);
		}
	}
	
	private void layoutLine(int end) {	
	}
	
	private void drawLine(boolean lineBreak) {
		int lineEnd = numObjects;
		int layoutEnd = numObjects;
		
		if(lineBreak == false) {
			for(int i = numObjects - 1; i > 0; i--) {
				if(objects[i].isSpace) {
					while(i > 1 && objects[i - 1].isSpace)
						i--;
					lineEnd = i + 1;
					layoutEnd = i;
					break;
				}
			}
		}

		calcAscentAndDescent(layoutEnd);
		layoutLine(layoutEnd);
		drawObjects(lineEnd);

		for(int i = 0; i < numObjects - lineEnd; i++) {
			TextObject temp = objects[i];
			
			objects[i] = objects[lineEnd + i];
			objects[lineEnd + i] = temp;
		}
		numObjects = numObjects - lineEnd;
	
		top += maxAscent + maxDescent;
	
		totalWidth = 0;
		for(int i = 0; i < numObjects; i++)
			totalWidth += objects[i].width;
		calcAscentAndDescent(numObjects);
	}
}
